#ifndef _FXG_PAINT_MODULE_
#define _FXG_PAINT_MODULE_

#include "fx_comm.h"

/**
 * @name Paint Error Flags
 */
/*@{*/
#define FXG_PAINT_ERROR_OK				0	/**< Success. */
#define FXG_PAINT_ERROR_FATAL			-1	/**< Fatal error. */
#define FXG_PAINT_ERROR_PARAMS			1	/**< User input parameter error. */
#define FXG_PAINT_ERROR_READ			2	/**< File read error */
#define FXG_PAINT_ERROR_WRITE			3	/**< File write error */
#define FXG_PAINT_ERROR_DATA			4	/**< File data error. */
#define FXG_PAINT_ERROR_MEM				5	/**< Not enough memory. */
#define	FXG_PAINT_ERROR_TYPE			6	/**< File type error. */
#define FXG_PAINT_ERROR_FILE_VERSION	7	/**< File version error. */
/*@}*/

/**
 * @name Constants for blending type. Undefined blend modes are not supported.
 * Same as the definition of FXDIB_BLEND_XXX in fx_dib.h.
 */
/*@{*/
#define FXG_BLEND_NORMAL						FXDIB_BLEND_NORMAL	                
#define FXG_BLEND_MULTIPLY						FXDIB_BLEND_MULTIPLY
#define FXG_BLEND_SCREEN						FXDIB_BLEND_SCREEN
#define FXG_BLEND_OVERLAY						FXDIB_BLEND_OVERLAY
#define FXG_BLEND_DARKEN						FXDIB_BLEND_DARKEN
#define FXG_BLEND_LIGHTEN						FXDIB_BLEND_LIGHTEN
#define FXG_BLEND_COLORDODGE					FXDIB_BLEND_COLORDODGE                 
#define FXG_BLEND_COLORBURN						FXDIB_BLEND_COLORBURN
#define FXG_BLEND_HARDLIGHT						FXDIB_BLEND_HARDLIGHT
#define FXG_BLEND_SOFTLIGHT						FXDIB_BLEND_SOFTLIGHT
#define FXG_BLEND_DIFFERENCE					FXDIB_BLEND_DIFFERENCE
#define FXG_BLEND_EXCLUSION						FXDIB_BLEND_EXCLUSION
/*@}*/

/**
 * @name Paint effects type
 */
/*@{*/
#define FXG_PE_SHAPEDYNAMICS		1		/**< Reserved now */
#define FXG_PE_DUALBRUSH			2		/**< Reserved now */
#define FXG_PE_SCATTERBRUSH			3		/**< Reserved now */
#define FXG_PE_TEXTURE				4		/**< Reserved now */
#define FXG_PE_COLORDYNAMICS		5		/**< Reserved now */
#define FXG_PE_OTHERDYNAMICS		6		/**< Reserved now */
#define FXG_PE_NOISE				7		/**< Reserved now */
#define FXG_PE_WETEDGE 				8		/**< Wet edge effects. */
#define FXG_PE_AIRBRUSH				9		/**< Reserved now */
#define FXG_PE_SMOOTH 				10		/**< Reserved now */
#define FXG_PE_PROTECTTEXTURE 		11		/**< Reserved now */
#define FXG_PE_MAX 					12		/**< Not a valid paint effect type, just indicate the up-bound */
/*@}*/

/**
 * @name Paint Nib types supported
 */
/*@{*/
#define FXG_NIB_ROUND				1
#define FXG_NIB_BASIC				2	/**< Reserved now */
#define FXG_NIB_MASK				3	/**< Reserved now */
#define FXG_NIB_SAMPLE				4	/**< Reserved now */
/*@}*/

/**@brief Use to create a customized layer nib, reserved now. */
#define FXG_NIB_CUSTOM				5

/**
 * @name Paint Nib file types
 */
/*@{*/
#define FXG_NIB_FILE_TYPE_FBR		1	/**< Reserved now */
#define FXG_NIB_FILE_TYPE_ABR		2	/**< Reserved now */
/*@}*/

/**
 * @name Paint types
 */
/*@{*/
#define FXG_PAINT_UNKNOWN			0
#define FXG_PAINT_PENCIL			1	/**< Reserved now */
#define FXG_PAINT_PEN				2
#define FXG_PAINT_ERASER			3	/**< Reserved now */
#define FXG_PAINT_BLUR				4	/**< Reserved now */
#define FXG_PAINT_SHARPEN			5	/**< Reserved now */
#define FXG_PAINT_MAX				6	/**< Not a valid paint type, just indicate the up-bound */
/*@}*/

/**@brief Flags of Nib cache limit. Default 10M. */
#define FXG_DEFAULT_CACHE_LIMIT		10*1024*1024

/**@brief Message types. */
#define FXG_MSG_GETNIBINFO			0x01
#define FXG_MSG_ADDPOINT			0x02
#define FXG_MSG_ADDPATHSEGMENT		0x03

class CFX_PathData;
class IFXG_PaintNib;

/**@brief Structure of Paint Nib Parameters. */
typedef struct
{
	FX_INT32			m_nDiameter;	/**< The nib diameter or line width. */
	FX_BOOL				m_bFlipX;		/**< Indicate the nib whether be horizontal flip. */
	FX_BOOL				m_bFlipY;		/**< Indicate the nib whether be vertical flip. */
	FX_FLOAT			m_fAngle;		/**< Indicate the nib whether be rotate. In range [0, 360). */
	FX_FLOAT			m_fRoundness;	/**< Indicate the nib whether be pinch flat. */
	FX_FLOAT			m_fDashScale;	/**< The range is (0, n), n is infinity. */

	union 
	{
		FX_FLOAT		m_fHardness;	/**< Valid in FXG_NIB_ROUND, the range is [0, 1]. */
		CFX_PathData*	m_pPath;		/**< Valid in FXG_NIB_BASIC, reserved now. */
		CFX_DIBitmap*	m_pPattern;		/**< Valid in FXG_NIB_MASK and FXG_NIB_SAMPLE, reserved now. */
	};
} FXG_NIB_PARAMS;

/** @brief Paint effects interface. */
class IFXG_PaintEffects
{
public:
	/**
	 * Get the paint effect type defined in FXG_PE_XXX 
	 *
	 * @return The Paint effect type
	 */
	virtual FX_INT32			GetSubType() const = 0;

	/**
	 * Get the paint effect control parameters. Reserved now.
	 *
	 * @return A pointer to the paint effect parameters if exist, otherwise NULL.
	 */
	virtual FX_LPVOID			GetParams() = 0;

	/**
	 * Set paint effect status.
	 *
	 * @param[in] bValid	Indicate whether the current paint effect is validated. 	
	 */
	virtual void				SetValid(FX_BOOL bValid) = 0;

	/**
	 * Get the paint effect status.
	 *
	 * @return TRUE indicate the paint effect is validated.
	 */
	virtual FX_BOOL				GetValid() const = 0;
};

/**@brief Paint nib interface. */
class IFXG_PaintNib
{
public:
	/**
	 * Get the paint nib type defined in FXG_NIB_XXX 
	 *
	 * @return The paint nib type
	 */
	virtual FX_INT32			GetType() const = 0;

	/**
	 * Get the paint nib type defined in FXG_NIB_XXX 
	 *
	 * @return The paint nib type
	 */
	virtual const CFX_DIBitmap*	GetNib() const = 0;

	/**
	 * Get paint nib name.
	 *
	 * @return A pointer to the byte string of paint nib name. 
	 */
	virtual FX_LPCSTR			GetName() const = 0;

	/**
	 * Get paint nib parameters. User can change the parameters according to nib type.
	 *
	 * @return A pointer to the paint nib parameters. 
	 */
	virtual FXG_NIB_PARAMS*		GetParams() = 0;

	/**
	 * Get paint effect according to FXG_PE_XXX.
	 *
	 * @return A pointer to the IFXG_PaintEffects. 
	 */
	virtual IFXG_PaintEffects*	GetEffects(FX_INT32 nEffect) = 0;
};

/**
 * @name Ink point Structure
 */
/*@{*/

/**@brief Point flags used in FXG_INK_POINT */
#define FXG_PT_LINETO			0x02
#define FXG_PT_MOVETO			0x04
#define FXG_PT_ENDPATH			0x08

/**@brief Structure of point struct used in IFXG_InkPath */
typedef struct
{
	FX_INT32 m_nFlag;		/**< The flag defined above, FXG_PT_XXX. */
	FX_FLOAT m_fPointX;		/**< The x-coordinate of the point. */
	FX_FLOAT m_fPointY;		/**< The y-coordinate of the point. */
	FX_FLOAT m_fPressure;	/**< The pressure of the point, in range [0, 1]. */
	FX_FLOAT m_fGradient;	/**< The gradient of the point, reserved now. */
	FX_FLOAT m_fAngle;		/**< The angle of the point, reserved now. */
} FXG_INK_POINT;
typedef CFX_ArrayTemplate<FXG_INK_POINT*>	CFXG_InkPointArray;

/**@brief Structure of pressure sensitive ink point array for serialize. Reserved now. */
typedef struct  
{
	FX_INT32			m_nDiameter;
	FXG_Color			m_Color;
	CFXG_InkPointArray	m_PtArray;
} FXG_PSI_DATA;

/*@}*/

/**
 * @name Flags of PSI Vector
 */
/*@{*/
#define FXG_PSI_TYPE_PATH	1	/**< Indicate the CFX_PathData as the PSI DATA. */
#define FXG_PSI_TYPE_DATA	2	/**< Indicate the FXG_PSI_DATA as the PSI DATA. */
/*@}*/

/**
 * @name Specific path filter, most of them could be used together except that FXG_PATH_FILTER_DIB and FXG_PATH_FILTER_VECTOR are mutually exclusive.
 */
/*@{*/
#define FXG_PATH_FILTER_SIMULATION	0	/**< If this filter turn on, the default sensitive filter will be repalced. */
#define FXG_PATH_FILTER_DIB			1	/**< This filter is the default one. If this filter turn on, IFXG_Paint render dib real time. */
#define FXG_PATH_FILTER_VECTOR		2	/**< Only this filter turn on, IFXG_Paint could render path real time.*/
#define FXG_PATH_FILTER_PSI			3	/**< Only this filter turn on, IFXG_InkPath could genelate a vectored data. */
/*@}*/

/** @brief Pressure sensitive ink path interface. */
class IFXG_InkPath
{
public:
	/**
	 * Add the pressure sensitive ink point to the path
	 * 
	 * @param[in] point			The point of pressure sensitive ink.
	 */
	virtual void				AddPoint(const FXG_INK_POINT& point) = 0;

	/**
	 * Generate the PSI data (A vectored data).
	 *
	 * @param[in] nType			Defined above, FXG_PSI_TYPE_XXX
	 * @param[out] pData		A Pointer to the vectored data. Caller need to interpret the data (s)he needed according to nType. 
	 *
	 * @return TRUE indicate the PSI vector data generate success, otherwise pData has no meaning.
	 */
	virtual FX_BOOL				GeneratePSI(FX_INT32 nType, FX_LPVOID& pData) = 0;
};

/**@brief User should implement the interface for customize paint render options. */
class IFXG_PaintRenderOption
{
public:
	/**
	 * Create a default rendering option if the user does not need to control the rendering option.
	 */
	static IFXG_PaintRenderOption*		CreateDefaultRenderOption();

	/**
	 * Destroy the current paint render option.
	 */
	virtual void				Destroy() = 0;

	/**
	 * @return The blending mode defined above, FXG_BLEND_XXX
	 */
	virtual FX_INT32			GetBlendMode() const = 0;

	/**
	 * @return The opacity of the paint foreground, in range [0, 1]
	 */
	virtual FX_FLOAT			GetOpacity() const = 0;

	/**
	 * @return The flow of the paint foreground, in range [0, 1]
	 */
	virtual FX_FLOAT			GetFlow() const = 0;

	/**
	 * Automatically erase means that if the canvas color of the starting point is located 
	 * is equal the foreground color, the paint will use background as paint color drawing in pencil mode.
	 * NOTE: The property effect in pencil mode(FXG_PAINT_PENCIL) only.
	 *
	 * @return TRUE indicate should be automatically erase
	 */
	virtual FX_BOOL				GetAutoErase() const = 0;
};

/**@brief Paint filter. */
class IFXG_Paint : public IFXG_Filter
{
public:
	/** 
	 * The paint type, defined in FXG_PAINT_XXX, such as, FXG_PAINT_PEN 
	 *
	 * @return The paint type.
	 */
	virtual FX_INT32			GetPaintType() const = 0;

	/** 
	 * Get the ink path, then if the paint is prepared, caller can add point to the path.
	 *
	 * @return The pointer to the IFXG_InkPath
	 */
	virtual IFXG_InkPath*		GetInkPath() const = 0;

	/** 
	 * Adds a specific path filter to IFXG_InkPath
	 * 
	 * @return TRUE indicate success, otherwise failure.
	 * @param[in] nFilter		A path filter type indicate in FXG_PATH_FILTER_XXX above.
	 */
	virtual FX_BOOL AddPathFilter(FX_INT32 nFilter) = 0;
	
	/** 
	 * Removes a specific path filter from IFXG_InkPath
	 * 
	 * @return TRUE indicate success, otherwise failure.
	 * @param[in] nFilter		A path filter type indicate in FXG_PATH_FILTER_XXX above.
	 */
	virtual FX_BOOL RemovePathFilter(FX_INT32 nFilter) = 0;

	/** 
	 * Get current paint nib.
	 *
	 * @return A pointer to the IFXG_PaintNib
	 */
	virtual IFXG_PaintNib*		GetPaintNib() const = 0;

	/** 
	 * REQUIRED. Set the paint nib as current nib. 
	 *
	 * @param[in] pPaintNib		A pointer to the IFXG_PaintNib
	 */
	virtual void				SetPaintNib(IFXG_PaintNib* pPaintNib) = 0;

	/** 
	 * REQUIRED. Set the rendering option to the paint. 
	 *
	 * @param[in] pPaintNib		A pointer to the IFXG_PaintRenderOption
	 */
	virtual void				SetRenderOption(IFXG_PaintRenderOption* pRenderOption) = 0;
};

/**
 * @brief Paint nib array.
 */
typedef CFX_ArrayTemplate<IFXG_PaintNib*> FXG_PaintNibArray;

/**
 * @brief Paint module manager. In order to use paint, you must initialize the module first.
 */
class IFXG_PaintModuleMgr
{
public:
	/**
	 * Create a Paint module.
	 */
	static IFXG_PaintModuleMgr* Create();

	/**
	 * Destroy the current Paint module.
	 */
	virtual void				Destroy() = 0;
	
	/** 
	 * Get the default canvas, and then you should config it.
	 *
	 * @return A pointer to the default canvas.
	 */
	virtual IFXG_Canvas*		GetCanvas() = 0;

	/** 
	 * Get a paint according paint type. The module manage will associate the paint and the default canvas. 
	 *
	 * @param[in] nPaintType	defined above, FXG_PAINT_XXX
	 * @return A pointer to IFXG_Paint.
	 */
	virtual IFXG_Paint*			GetPaint(FX_INT32 nPaintType) = 0;

	/** 
	 * Set the cache limit of the paint nib.
	 * OPTION. If the caller does not set it, the paint module will use FXG_DEFAULT_CACHE_LIMIT as default
	 *
	 * @param[in] dwLimitSize	The size of the cache limit
	 */
	virtual void				SetCacheLimit(FX_DWORD dwLimitSize) = 0;

	/** 
	 * Create a paint nib according to the nNibType.
	 * If the nNibType is FXG_NIB_CUSTOM, the paint module will create the nib according to the 
	 * canvas(clipped by clip region and the DIB data)
	 * The created paint nib managed by the paint module, caller could destroy it only by DestroyPaintNib.
	 * If caller does not destroy it manual, it will be free when the paint module Destroy or LoadPaintNib with replace.
	 *
	 * @param[in] pStrName		The paint nib name the caller wanna.
	 * @param[in] nNibType		The paint nib type defined above, FXG_NIB_XXX. If FXG_NIB_CUSTOM, the pParams value will be ignore.
	 * @param[in] pParams		The parameter of the nib according nNibType. defined as FXG_NIB_PARAMS.
	 * @return A pointer to IFXG_PaintNib, return NULL if failure.
	 */
	virtual IFXG_PaintNib*		CreatePaintNib(FX_LPCSTR pStrName, FX_INT32 nNibType, FX_LPVOID pParams = NULL) = 0;

	/** 
	 * If the caller believe that the paint nib is no longer useful, you can destroy it by the method.
	 *
	 * @param[in] pNib			The paint nib will bes destroyed.
	 * @return TRUE indicate success, otherwise failure.
	 */
	virtual FX_BOOL				DestroyPaintNib(IFXG_PaintNib* pNib) = 0;

	/** 
	 * Load a set of paint nibs from a file. Reserved now.
	 *
	 * @param[in] pFile			The stream access interface.
	 * @param[in] bReplace		The flags indicate a new set of paint nibs whether to replace the previous ones.
	 * @return A flag defined above, FXG_PAINT_ERROR_XXX
	 */
	virtual FX_INT32			LoadPaintNib(IFX_FileRead* pFile, FX_BOOL bReplace) = 0;

	/** 
	 * Save current set of paint nibs to a file. Reserved now.
	 *
	 * @param[in] pFile			The stream access interface.
	 * @param[in] nType			The flags indicate the encoding nib file's type.
	 * @return A flag defined above, FXG_PAINT_ERROR_XXX
	 */
	virtual FX_INT32			SavePaintNib(IFX_FileWrite* pFile, FX_INT32 nType = FXG_NIB_FILE_TYPE_FBR) = 0;

	/** 
	 * List all paint nibs of current set of paint nibs.
	 *
	 * @param[out] nib_array	It received a set of current paint nibs.
	 * @return TRUE indicate success, otherwise failure.
	 */
	virtual FX_BOOL				ListAllPaintNib(FXG_PaintNibArray& nib_array) const = 0;
};

#endif // _FXG_PAINT_MODULE_

